//
//  RichTest.m
//  RichTest
//
//  Created by Kenny Chen on 12/12/12.
//  Copyright (c) 2012年 Kenny Chen. All rights reserved.
//

#import "RichTest.h"
#import "RichError.h"

@implementation RichTest

- (void)setUp
{
    [super setUp];
    
    // Set-up code here.
    [self raiseAfterFailure];
    
    core = [[RichCore alloc] init];
    STAssertTrue(core != nil, @"Failed to configure RichCore");
}

- (void)tearDown
{
    // Tear-down code here.
    [core release];
    
    [super tearDown];
}

- (void)test_0_TableCorrectness
{
    NSLog(@"------------- Start testing table correctness -------------");
    
    // Test database table structure
    STAssertTrue([core checkTableCorrectness], @"Incorrect tables");
    
    NSLog(@"------------- End testing table correctness -------------");
}

- (void)test_1_Currency
{
    NSLog(@"------------- Start testing currency API -------------");
    
    // Test currency
    STAssertTrue([[core currency] count] > 0, @"Empty currency table");
    
    for (NSString *abbr in [[core currency] allKeys]) {
        NSLog(@"[%@] %@", abbr, [[core currency] objectForKey:abbr]);
    }
    
    NSLog(@"------------- End testing currency API -------------");
}

- (void)test_2_Account
{
    [core loadAccounts];
    
    for (RichAccount *a in [[core accounts] copy]) {
        STAssertTrue([core removeAccount:a.accountId] == RICH_OK, @"Delete account fail");
    }
    
    NSLog(@"------------- Start testing account API -------------");
    
    int num = [core loadAccounts];
    STAssertTrue(num >= 0, @"Unable to load from database");
    if (num == 0) NSLog(@"No account in database");
    else {
        for (RichAccount *a in [core accounts]) {
            NSLog(@"Account: [%d] %@", a.accountId, a.name);
        }
    }
    
    
    
    /*
     * Create account API test
     */
    RichAccount *account = [[RichAccount alloc] init];
    account.name = @"中國信託";
    account.type = AccountTypeDepositSavings;
    account.currencyCode = @"NTD";
    account.amount = 10000;
    account.property = AccountPropertyNone;
    account.description = @"Splashtop Salary";
    STAssertTrue([core createAccount:account] >= 0, @"Create account fail");
    [account release];
    
    account = [[RichAccount alloc] init];
    account.name = @"台灣企銀";
    account.type = AccountTypeDepositSavings;
    account.currencyCode = @"XXX";
    account.amount = 2000000;
    account.property = AccountPropertyNone;
    account.description = @"GwInstek Salary";
    STAssertTrue([core createAccount:account] == -ERROR_CORE_INVALID_PARM, @"Create account with invalid currency code fail");
    
    account = [[RichAccount alloc] init];
    account.name = @"台灣企銀";
    account.type = AccountTypeDepositSavings;
    account.currencyCode = @"NTD";
    account.amount = 2000000;
    account.property = AccountPropertyNone;
    account.description = @"GwInstek Salary";
    STAssertTrue([core createAccount:account] >= 0, @"Create second account fail");
    
    
    
    /*
     * Update account API test
     */
    STAssertTrue([core loadAccounts] >= 0, @"Unable to load from database");
    
    // account.accountId = 2
    account.name = @"中國信託";
    account.type = AccountTypeCredit;
    account.currencyCode = @"NTD";
    account.amount = 10000;
    account.property = AccountPropertyDefault;
    account.description = @"US Dollars";
    STAssertTrue([core updateAccount:account] == -ERROR_CORE_OCCUPIED, @"Update account with the same name fail");
    
    account.name = @"現金";
    account.type = AccountTypeCredit;
    account.currencyCode = @"NTD";
    account.amount = 20000;
    account.property = AccountPropertyDefault;
    account.description = @"Money in my pocket";
    STAssertTrue([core updateAccount:account] == RICH_OK, @"Update account fail");
    [account release];
    
    account = [[RichAccount alloc] init];
    account.accountId = 100;
    account.name = @"Whatever";
    account.type = AccountTypeCredit;
    account.currencyCode = @"USD";
    account.amount = 9999999;
    account.property = AccountPropertyDefault;
    account.description = @"US Dollars";
    STAssertTrue([core updateAccount:account] == -ERROR_CORE_ID_NOT_FOUND, @"Update non-exist account fail");
    
    
    
    /*
     * Delete account API test
     */
    STAssertTrue([core removeAccount:account.accountId] == -ERROR_CORE_ID_NOT_FOUND, @"Delete non-exist account fail");
    [account release];
    
    NSLog(@"------------- End testing account API -------------");
}

- (void)test_3_Category
{
    STAssertTrue([core loadCategories] >= 0, @"Load category fail");
    
    // Delete all exists categories
    for (NSNumber *c in [[core category] allKeys]) {
        [core deleteCategory:[c integerValue]];
    }
    
    NSLog(@"------------- Start testing category API -------------");
    
    STAssertTrue([core createCategory:0x10000 name:@"支出"] >= 0, @"Create category fail");
    STAssertTrue([core createCategory:0x10000 name:@"錯誤測試"] < 0, @"Create category with same code fail");
    STAssertTrue([core createCategory:0x20000 name:@"收入"] >= 0, @"Create second category fail");
    STAssertTrue([core createCategory:0x30000 name:@"支出"] < 0, @"Create category with same name fail");
    STAssertTrue([core createCategory:0x30000 name:@"轉帳"] >= 0, @"Create third category fail");
    STAssertTrue([core createCategory:0x10100 name:@"食"] >= 0, @"");
    STAssertTrue([core createCategory:0x10200 name:@"衣"] >= 0, @"");
    STAssertTrue([core createCategory:0x20100 name:@"薪資"] >= 0, @"");
    STAssertTrue([core createCategory:0x20200 name:@"獎金"] >= 0, @"");
    STAssertTrue([core createCategory:0x30100 name:@"轉帳"] >= 0, @"");
    STAssertTrue([core createCategory:0x30200 name:@"交易"] >= 0, @"");
    STAssertTrue([core createCategory:0x10101 name:@"早餐"] >= 0, @"");
    STAssertTrue([core createCategory:0x10102 name:@"午餐"] >= 0, @"");
    STAssertTrue([core createCategory:0x10103 name:@"晚餐"] >= 0, @"");
    STAssertTrue([core createCategory:0x20101 name:@"浪橋"] >= 0, @"");
    STAssertTrue([core createCategory:0x20201 name:@"分紅"] >= 0, @"");
    STAssertTrue([core createCategory:0x30101 name:@"現金提款"] >= 0, @"");
    STAssertTrue([core createCategory:0x30102 name:@"銀行轉帳"] >= 0, @"");
    STAssertTrue([core createCategory:0x30201 name:@"信用卡繳款"] >= 0, @"");
    
    STAssertTrue([core loadCategories] >= 0, @"Load category fail");
    
    for (NSNumber *c in [[core category] allKeys]) {
        NSLog(@"Category: %d:%@", [c integerValue], [[core category] objectForKey:c]);
    }
    
    STAssertTrue([core updateCategory:0x20101 name:@"固緯"] == RICH_OK, @"Update category fail");
    
    STAssertTrue([core loadCategories] >= 0, @"Load category fail");
    
    NSLog(@"Update: 0x20101:%@", [[core category] objectForKey:[NSNumber numberWithInt:2]]);
    
    NSLog(@"------------- End testing category API -------------");
}

- (void)test_4_TransactionGeneral
{
    NSLog(@"------------- Start testing general transaction API -------------");
    
    [core loadAccounts];
    for (RichAccount *a in [core accounts]) {
        NSLog(@"Account: [%d] %@", a.accountId, a.name);
    }
    
    [core loadCategories];
    
    STAssertTrue([core loadTransactions:kTransactionTypeGeneral where:nil beginAtIndex:0 limit:100] >= 0, @"Load general transaction fail");
    
    // Delete all exists general transactions
    NSMutableArray *transactions = [[core transactions] objectForKey:kTransactionTypeGeneral];
    for (RichTransactionGeneral *__trans in transactions) {
        [core deleteTransaction:__trans.transId type:kTransactionTypeGeneral];
    }
    
    // Expend Test
    RichTransactionGeneral *trans = [[RichTransactionGeneral alloc] init];
    trans.date = [core stringFromDate:[NSDate date] format:nil];
    trans.categoryCode = 0x10101;
    trans.accountFrom = [(RichAccount *)[[core accounts] objectAtIndex:1] accountId]; // 現金
    trans.accountTo = 0;
    trans.installmentPaymentTimes = 0;
    trans.installmentDownPayment = 0.0f;
    trans.installmentRate = 0.0f;
    trans.installmentPeriod = TransactionInstallmentPeriodMonthly;
    trans.installmentMade = 0;
    trans.commission = 0.0f;
    trans.amount = 200;
    trans.numberOfReceipt = 1;
    trans.receiptSerial = @"CK05281225";
    trans.comment = @"Starbucks";
    
    STAssertTrue([core createTransaction:(id *)trans type:kTransactionTypeGeneral] == RICH_OK, @"");
    
    // Income Test
    trans.date = [core stringFromDate:[NSDate date] format:nil];
    trans.categoryCode = 0x20101;
    trans.accountFrom = 0;
    trans.accountTo = [(RichAccount *)[[core accounts] objectAtIndex:0] accountId]; // 中國信託
    trans.amount = 50000;
    trans.comment = @"GwInstek";
    
    STAssertTrue([core createTransaction:(id *)trans type:kTransactionTypeGeneral] == RICH_OK, @"");
    
    // Transfer Test
    trans.date = [core stringFromDate:[NSDate date] format:nil];
    trans.categoryCode = 0x30101;
    trans.accountFrom = [(RichAccount *)[[core accounts] objectAtIndex:0] accountId]; // 中國信託
    trans.accountTo = [(RichAccount *)[[core accounts] objectAtIndex:1] accountId]; // 現金
    trans.commission = 12;
    trans.amount = 1000;
    trans.comment = @"提款1000元";
    
    STAssertTrue([core createTransaction:(id *)trans type:kTransactionTypeGeneral] == RICH_OK, @"");
    
    // Error Test
    trans.categoryCode = 0x999999; // Wrong code
    trans.accountFrom = [(RichAccount *)[[core accounts] objectAtIndex:1] accountId];
    trans.accountTo = 0;
    trans.amount = 100;
    
    STAssertTrue([core createTransaction:(id *)trans type:kTransactionTypeGeneral] < 0, @"");
    
    trans.categoryCode = 0x10101;
    trans.accountFrom = 0; // Wrong account
    trans.accountTo = 0;
    trans.commission = 0;
    trans.amount = 200;
    
    STAssertTrue([core createTransaction:(id *)trans type:kTransactionTypeGeneral] < 0, @"");
    
    trans.categoryCode = 0x10101;
    trans.accountFrom = 0; // Wrong account
    trans.accountTo = [(RichAccount *)[[core accounts] objectAtIndex:1] accountId]; // Wrong account
    trans.commission = 0;
    trans.amount = 200;
    
    STAssertTrue([core createTransaction:(id *)trans type:kTransactionTypeGeneral] < 0, @"");
    
    trans.categoryCode = 0x20109; // Wrong code
    trans.accountFrom = [(RichAccount *)[[core accounts] objectAtIndex:0] accountId];
    trans.accountTo = [(RichAccount *)[[core accounts] objectAtIndex:1] accountId];
    trans.commission = 0;
    trans.amount = 20000;
    
    STAssertTrue([core createTransaction:(id *)trans type:kTransactionTypeGeneral] < 0, @"");
    
    trans.categoryCode = 0x20101;
    trans.accountFrom = [(RichAccount *)[[core accounts] objectAtIndex:0] accountId]; // Wrong account
    trans.accountTo = [(RichAccount *)[[core accounts] objectAtIndex:1] accountId];
    trans.commission = 0;
    trans.amount = 20000;
    
    STAssertTrue([core createTransaction:(id *)trans type:kTransactionTypeGeneral] < 0, @"");
    
    trans.categoryCode = 0x20101;
    trans.accountFrom = 0;
    trans.accountTo = 99; // Wrong account id
    trans.commission = 0;
    trans.amount = 20000;
    
    STAssertTrue([core createTransaction:(id *)trans type:kTransactionTypeGeneral] < 0, @"");
    
    trans.categoryCode = 0x30101;
    trans.accountFrom = 0; // Wrong account
    trans.accountTo = [(RichAccount *)[[core accounts] objectAtIndex:1] accountId];
    trans.commission = 0;
    trans.amount = 1000;
    
    STAssertTrue([core createTransaction:(id *)trans type:kTransactionTypeGeneral] < 0, @"");
    
    trans.categoryCode = 0x30101;
    trans.accountFrom = [(RichAccount *)[[core accounts] objectAtIndex:1] accountId];
    trans.accountTo = 0; // Wrong account
    trans.commission = 0;
    trans.amount = 1000;
    
    STAssertTrue([core createTransaction:(id *)trans type:kTransactionTypeGeneral] < 0, @"");
    
    NSLog(@"------------- End testing general transaction API -------------");
}

#if 1
- (void)test_n_DeleteAll
{
    // Delete all transactions
    STAssertTrue([core loadTransactions:kTransactionTypeGeneral where:nil beginAtIndex:0 limit:100] >= 0, @"Load general transaction fail");
    NSMutableArray *transactions = [[core transactions] objectForKey:kTransactionTypeGeneral];
    for (RichTransactionGeneral *__trans in transactions) {
        [core deleteTransaction:__trans.transId type:kTransactionTypeGeneral];
    }
    
    // Delete all category
    STAssertTrue([core loadCategories] >= 0, @"Unable to load from database");
    for (NSNumber *c in [[core category] allKeys]) {
        NSLog(@"Removing %d:%@", [c integerValue], [[core category] objectForKey:c]);
        STAssertTrue([core deleteCategory:[c intValue]] == RICH_OK, @"Delete category fail");
    }
    
    // Delete all account
    STAssertTrue([core loadAccounts] >= 0, @"Unable to load from database");
    for (RichAccount *a in [[core accounts] copy]) {
        NSLog(@"Delete %@", a.name);
        STAssertTrue([core deleteAccount:a.accountId] == RICH_OK, @"[Fail]");
    }
}
#endif

@end
